Sort of crossposted from:
http://www.perlmonks.org/index.pl?node_id=369354
A new monk at the Monastery wanted to be able to use the following syntax to get/set properties
my $name = $obj->name;
$obj->name = "Limbic";
Ok - use an lvaluable sub right. Well the new monk also wanted to be able to pre/post process like C# (which I don't have any knowledge of):
$obj->name = "Limbic";
print $obj->name, "\n"; # "Limbic post processed"
After getting nowhere trying to convince the monk to use the conventional syntax, I decided to give it a shot. I came up with the following in about 20 minutes (I had never used lvaluable subs before and have only used tied variables a few times)
package magic;
sub TIESCALAR {
my $class = shift;
die "Incorrect number of parameters" if @_ % 2;
my $self = bless {}, $class;
$self->_Init(@_);
return $self;
}
sub _Init {
my ($self, %opt) = @_;
$self->{PRE} = $opt{PRE} || sub { return uc $_[0] };
$self->{POST} = $opt{POST} || sub {
my $val = shift;
$val =~ s/FOO/BAR/;
return $val;
};
return;
}
sub STORE {
my ($self, $value) = @_;
$value = $self->{PRE}->( $value );
$value = $self->{POST}->( $value );
$self->{VAL} = $value;
}
sub FETCH { return $_[0]->{VAL} }
########################################
package cool;
sub new {
my $class = shift;
tie my $name, "magic", @_;
bless \$name, $class;
}
sub name :lvalue {
${$_[0]};
}
########################################
package main;
tie my $string, "magic";
$string = 'My left foot';
print "$string\n";
my $obj = cool->new( 'POST' => sub { return reverse $_[0] } );
$obj->name = "My right foot";
print $obj->name, "\n";
I posted the following questions after the response:
Is there a better way of doing this?
Is it hard to extend Attribute::Property to do this?
If this is the way to do it, how can it be wrapped up in a module like Attribute::Property to make it easier to use?
Since I haven't (as of yet) gotten any feedback at the Monastery I figured I would throw it out here as well.